/*
 * MIT License
 *
 * Copyright (c) 2023 北京凯特伟业科技有限公司
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package com.je.meta.rpc;

import com.je.common.base.DynaBean;
import com.je.common.base.JsonBuilder;
import com.je.common.base.constants.table.ColumnType;
import com.je.common.base.constants.tree.TreeNodeType;
import com.je.common.base.entity.func.FuncRelationField;
import com.je.common.base.service.rpc.BeanService;
import com.je.common.base.util.ArrayUtils;
import com.je.common.base.util.DynaBeanUtil;
import com.je.common.base.util.StringUtil;
import com.je.core.entity.extjs.JSONTreeNode;
import org.apache.servicecomb.provider.pojo.RpcReference;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
public class MetaBeanRpcServiceImpl implements BeanService {

    @RpcReference(microserviceName = "meta", schemaId = "metaBeanRpcService")
    private BeanService beanService;

    @Override
    public DynaBean getResourceTable(String tableCode) {
        return beanService.getResourceTable(tableCode);
    }

    @Override
    public String getPKeyFieldNames(DynaBean dynaBean) {
        return beanService.getPKeyFieldNames(dynaBean);
    }

    @Override
    public String getPKeyFieldNamesByTableCode(String tableCode) {
        return beanService.getPKeyFieldNamesByTableCode(tableCode);
    }

    @Override
    public String getForeignKeyField(String tableCode, String parentTableCode, String parentPkCode, List<FuncRelationField> relatedFields) {
        return beanService.getForeignKeyField(tableCode, parentTableCode, parentPkCode, relatedFields);
    }

    @Override
    public String[] getNames(DynaBean dynaBean) {
        HashMap valueMap = dynaBean.getValues();
        String[] names = new String[valueMap.size()];
        int i = 0;
        for (Iterator it = valueMap.keySet().iterator(); it.hasNext(); i++) {
            names[i] = (String) it.next();
        }
        return names;
    }

    @Override
    public String getNames4Sql(DynaBean table) {
        StringBuilder names = new StringBuilder();
        //根据ResourceTable得到DyanBean
        DynaBean dynaBean = getDynaBeanByResourceTable(table);
        String[] arrayName = getNames(dynaBean);
        for (String name : arrayName) {
            if (!name.startsWith(StringUtil.DOLLAR)) {
                names.append(name + ",");
            }
        }
        names.setLength(names.length() - 1);
        return names.toString();
    }

    @Override
    public String getUpdateInfos4Sql(DynaBean resourceTable, Map<String, Object> values) {
        StringBuilder names = new StringBuilder();
        DynaBean dynaBean = getDynaBeanByResourceTable(resourceTable);
        String[] arrayName = getNames(dynaBean);
        for (String name : arrayName) {
            if (!name.startsWith(StringUtil.DOLLAR)) {
                if (values.get(name) != null) {
                    names.append(name + "=:" + name + ",");
                }
            }
        }
        names.setLength(names.length() - 1);
        return names.toString();
    }

    @Override
    public String getNames2DynaBean4Sql(DynaBean dynaBean) {
        StringBuilder names = new StringBuilder();
        String[] arrayName = getNames(dynaBean);
        for (String name : arrayName) {
            if (!name.startsWith(StringUtil.DOLLAR)) {
                names.append(name + ",");
            }
        }
        names.setLength(names.length() - 1);
        return names.toString();
    }

    @Override
    public String getValues4Sql(DynaBean table) {
        StringBuilder values = new StringBuilder();
        //根据ResourceTable得到DyanBean
        DynaBean dynaBean = getDynaBeanByResourceTable(table);
        String[] arrayName = getNames(dynaBean);
        for (String name : arrayName) {
            if (!name.startsWith(StringUtil.DOLLAR)) {
                values.append(":" + name + ",");
            }
        }
        values.setLength(values.length() - 1);
        return values.toString();
    }

    @Override
    public DynaBean getDynaBeanByResourceTable(DynaBean table) {
        DynaBean dynaBean = new DynaBean(table.getStr("RESOURCETABLE_TABLECODE"));
        List<DynaBean> columns = (List<DynaBean>) table.get(BeanService.KEY_TABLE_COLUMNS);
        for (DynaBean column : columns) {
            dynaBean.set(column.getStr("TABLECOLUMN_CODE"), "");
        }
        return dynaBean;
    }

    @Override
    public Object[] getValues(DynaBean dynaBean) {
        HashMap valueMap = dynaBean.getValues();
        Object[] values = new String[valueMap.size()];
        int i = 0;
        for (Iterator it = valueMap.keySet().iterator(); it.hasNext(); i++) {
            values[i] = valueMap.get((String) it.next());
        }
        return values;
    }

    @Override
    public List<DynaBean> buildUpdateList(String updateStr, String tableCode) {
        List<DynaBean> beans = new ArrayList<DynaBean>();
        if (StringUtil.isEmpty(updateStr)) {
            return beans;
        }
        List<Map> sqlMapList = JsonBuilder.getInstance().fromJsonArray(updateStr);
        for (int i = 0; i < sqlMapList.size(); i++) {
            Map sqlMap = sqlMapList.get(i);
            DynaBean dynaBean = new DynaBean(tableCode, true);
            for (Object obj : sqlMap.entrySet()) {
                Map.Entry entry = (Map.Entry) obj;
                String k = StringUtil.getDefaultValue(entry.getKey(), "");
                if (StringUtil.isNotEmpty(k)) {
                    if(sqlMap.get(k) instanceof String && sqlMap.get(k).equals("null")){
                        dynaBean.set(k, null);
                    }else {
                        dynaBean.set(k, sqlMap.get(k));
                    }
                }
            }
            beans.add(dynaBean);
        }
        return beans;
    }

    @Override
    public String[] getDynaBeanIdArray(List<DynaBean> beans, String pkCode) {
        String[] idArray = new String[beans.size()];
        for (Integer i = 0; i < beans.size(); i++) {
            idArray[i] = beans.get(i).getStr(pkCode, "");
        }
        return idArray;
    }

    @Override
    public DynaBean initSysTable(String tableCode) {
        return beanService.initSysTable(tableCode);
    }

    @Override
    public String getFieldNames(DynaBean resourceTable, String[] excludes) {
        List<DynaBean> columns = (List<DynaBean>) resourceTable.get(BeanService.KEY_TABLE_COLUMNS);
        StringBuffer fieldCodes = new StringBuffer();
        for (DynaBean column : columns) {
            String columnCode = column.getStr("TABLECOLUMN_CODE");
            if (!ArrayUtils.contains(excludes, columnCode)) {
                fieldCodes.append(columnCode + ",");
            }
        }
        fieldCodes.deleteCharAt(fieldCodes.length() - 1);
        return fieldCodes.toString();
    }

    @Override
    public String getSysQueryFields(String tableCode) {
        DynaBean resourceTable = getResourceTable(tableCode);
        List<DynaBean> columns = (List<DynaBean>) resourceTable.get(BeanService.KEY_TABLE_COLUMNS);
        StringBuffer fieldCodes = new StringBuffer();
        for (DynaBean column : columns) {
            if ("SYS".equalsIgnoreCase(column.getStr("TABLECOLUMN_CLASSIFY"))) {
                String columnCode = column.getStr("TABLECOLUMN_CODE");
                fieldCodes.append(columnCode + ",");
            }
        }
        fieldCodes.deleteCharAt(fieldCodes.length() - 1);
        return fieldCodes.toString();
    }

    @Override
    public String getProQueryFields(String tableCode) {
        DynaBean resourceTable = getResourceTable(tableCode);
        List<DynaBean> columns = (List<DynaBean>) resourceTable.get(BeanService.KEY_TABLE_COLUMNS);
        StringBuffer fieldCodes = new StringBuffer();
        for (DynaBean column : columns) {
            if ("PRO".equalsIgnoreCase(column.getStr("TABLECOLUMN_CLASSIFY"))) {
                String columnCode = column.getStr("TABLECOLUMN_CODE");
                fieldCodes.append(columnCode + ",");
            }
        }
        fieldCodes.deleteCharAt(fieldCodes.length() - 1);
        return fieldCodes.toString();
    }

    @Override
    public String getQueryFields(String tableCode, String[] excludes) {
        DynaBean resourceTable = getResourceTable(tableCode);
        List<DynaBean> columns = (List<DynaBean>) resourceTable.get(BeanService.KEY_TABLE_COLUMNS);
        StringBuffer fieldCodes = new StringBuffer();
        for (DynaBean column : columns) {
            String columnCode = column.getStr("TABLECOLUMN_CODE");
            if (!ArrayUtils.contains(excludes, columnCode)) {
                fieldCodes.append(columnCode + ",");
            }
        }
        fieldCodes.deleteCharAt(fieldCodes.length() - 1);
        return fieldCodes.toString();
    }

    @Override
    public String getNoClobQueryFields(String tableCode) {
        DynaBean resourceTable = getResourceTable(tableCode);
        List<DynaBean> columns = (List<DynaBean>) resourceTable.get(BeanService.KEY_TABLE_COLUMNS);
        StringBuffer fieldCodes = new StringBuffer();
        for (DynaBean column : columns) {
            if (!ColumnType.CLOB.equalsIgnoreCase(column.getStr("TABLECOLUMN_TYPE")) || !ColumnType.BIGCLOB.equalsIgnoreCase(column.getStr("TABLECOLUMN_TYPE"))) {
                String columnCode = column.getStr("TABLECOLUMN_CODE");
                fieldCodes.append(columnCode + ",");
            }
        }
        fieldCodes.deleteCharAt(fieldCodes.length() - 1);
        return fieldCodes.toString();
    }

    @Override
    public JSONTreeNode getTreeTemplate(String tableCode) {
        DynaBean resourceTable = getResourceTable(tableCode);
        List<DynaBean> tableColumns = (List<DynaBean>) resourceTable.get(BeanService.KEY_TABLE_COLUMNS);
        JSONTreeNode template = buildJSONTreeNodeTemplate(tableColumns);
        return template;
    }

    @Override
    public JSONTreeNode buildJSONTreeNodeTemplate(List<DynaBean> columns) {
        JSONTreeNode node = new JSONTreeNode();
        try {
            for (Object eachObj : columns) {
                DynaBean column;
                if (eachObj instanceof LinkedHashMap) {
                    column = DynaBeanUtil.convert(eachObj);
                } else {
                    column = (DynaBean) eachObj;
                }
                String code = column.getStr("TABLECOLUMN_CODE");
                String treeType = column.getStr("TABLECOLUMN_TREETYPE");

                if (treeType.equals(TreeNodeType.ID.toString())) {
                    node.setId(code);
                } else if (treeType.equals(TreeNodeType.TEXT.toString())) {
                    node.setText(code);
                } else if (treeType.equals(TreeNodeType.CODE.toString())) {
                    node.setCode(code);
                } else if (treeType.equals(TreeNodeType.PARENT.toString())) {
                    node.setParent(code);
                } else if (treeType.equals(TreeNodeType.NODEINFO.toString())) {
                    node.setNodeInfo(code);
                } else if (treeType.equals(TreeNodeType.NODEINFOTYPE.toString())) {
                    node.setNodeInfoType(code);
                } else if (treeType.equals(TreeNodeType.NODETYPE.toString())) {
                    node.setNodeType(code);
                } else if (treeType.equals(TreeNodeType.ICON.toString())) {
                    node.setIcon(code);
                } else if (treeType.equals(TreeNodeType.ICONCOLOR.toString())) {
                    node.setIconColor(code);
                } else if (treeType.equals(TreeNodeType.DISABLED.toString())) {
                    node.setDisabled(code);
                } else if (treeType.equals(TreeNodeType.NODEPATH.toString())) {
                    node.setNodePath(code);
                } else if (treeType.equals(TreeNodeType.DESCRIPTION.toString())) {
                    node.setDescription(code);
                } else if (treeType.equals(TreeNodeType.ORDERINDEX.toString())) {
                    node.setOrderIndex(code);
                } else if (treeType.equals(TreeNodeType.LAYER.toString())) {
                    node.setLayer(code);
                } else if (treeType.equals(TreeNodeType.TREEORDERINDEX.toString())) {
                    node.setTreeOrderIndex(code);
                } else if (treeType.equals(TreeNodeType.OTHERBEANFIELD.toString())) {
                    node.addOtherBeanFiled(code);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return node;
    }

}
